AWSアカウントごとに通知先を分ける EventBridge アーキテクチャ案
AWSアカウントごとに通知先を分けたい
今回の話の前提は マルチアカウントサービス です。 AWS Organizations や AWS Security Hub、Amazon GuardDuty などがそれに当たります。 これらのサービスは、代表1アカウント上で複数AWSアカウントを集中的に操作・管理できます。 例えば AWS Security Hub では 代表1アカウント上で 他アカウントの セキュリティ検出結果を集約、集中管理できます。
これらマルチアカウントサービスを使っていると AWSアカウントごとに異なる通知先へ振り分けたい ケースが出てきます。 「このプロジェクトに関連するAWSアカウント通知はここに」、 「あのプロジェクトに関連するAWSアカウント通知はあそこに」といったイメージです。 その際の「良いアーキテクチャ」を設計したいです。
もともとは下図のようなアーキテクチャで対応していました。 振り分けの単位で 「EventBridgeルール、SNSトピック」を作成するアーキテクチャです。
AWS CloudFormation など IaC ツールを使うことで容易に複製できるので、
このアーキテクチャでも悪くはないです。
しかし、例えば 「AWS Security Hub で通知する検出結果の重要度を変えたい」
といった変更作業が出てきたときに、全ての EventBridgeルールを変更する必要があります。
少し面倒に感じてしまいます。
イベントバス間連携を活用できそう
「 同一リージョン・同一アカウント内のイベントバス間連携 で (前述の) 課題を解決できそう」と考えました。 下図のような構成です。
- EventBride イベントバスを 2つ利用
default
: AWSサービスからイベントを受信custom security
: 新規作成するカスタムイベントバス。Security Hub のイベントを受信するように構成する
- EventBride ルールによるフィルタリングを 2段階に分離
Security Hub rule
: Security Hub の イベントを検知 → custom security イベントバスへ送信Accounts rule
: 特定アカウントのイベントを検知 → SNSトピックへ送信
フィルタリングを 2段階に分離することで、通知するしきい値の変更作業を簡素化できます。
つまり 「AWS Security Hub で通知する検出結果の重要度を変えたい」
といったケースの場合、
Security Hub rule
の変更のみで済みます。
次章で実際に構築してみます。
※1: 「同一リージョン・同一アカウント内のイベントバス間連携」は比較的新しい(2021年)機能アップデートです。 以下記事を参照ください。
※2: 今回は試していませんが、他にも良いアーキテクチャはありそうです。 例えば SNSトピックの サブスクリプションフィルター を活用する方法です(下図参照)。
作ってみる
1. カスタムイベントバスへ送信するところまで
- カスタムイベントバス
- カスタムイベントバスに送信する EventBridgeルール
これらリソースを作っていきます。
カスタムイベントバス
[EventBridge > イベントバス > イベントバスを作成] からイベントバスを作成します。
名前のみ指定 ( custom-securityhub-bus
)、それ以外はデフォルトでOKです。
カスタムイベントバスに送信する EventBridgeルール
[EventBridge > ルール > ルールを作成] からルールを作成します。
ルール名を適当に記載 ( capture-securityhub-findings
など )、イベントバスは default
です
イベントパターンは下記のようにしています。 (参考: Security Hub 検出結果のフィルタリング例 | DevelopersIO )
{ "detail": { "findings": { "Compliance": { "Status": [{ "anything-but": "PASSED" }] }, "ProductName": ["Security Hub"], "RecordState": ["ACTIVE"], "Severity": { "Label": ["CRITICAL", "HIGH"] }, "Workflow": { "Status": ["NEW"] } } }, "detail-type": ["Security Hub Findings - Imported"], "source": ["aws.securityhub"] }
ターゲットは「先程作成したカスタムイベントバス」です。
※ターゲットをカスタムイベントバスにする際に IAMロール を作成する必要があります。 以下のような設定値の IAMロールを事前に作成しておきましょう。
- 信頼関係ポリシー: EventBridgeサービス (
"events.amazonaws.com"
) からの"sts:AssumeRole"
を許可 - ロールポリシー: 該当カスタムイベントバスへの
"events:PutEvents"
を許可
2. メッセージ送信するところまで
- SNSトピック
- EventBridgeルール ( from カスタムイベントバス )
これらリソースを作っていきます。
( 今回は 1プロジェクト分、つまり 図の AAA 関連リソース
のみ構築してみます)
SNSトピック
SNSトピックを作成しておきます。サブスクリプション設定も済ませておきましょう。
EventBridgeルール ( from カスタムイベントバス )
[EventBridge > イベントバス > イベントバスを作成] からイベントバスを作成します。
名前を適当に記入して ( account-selector-aaa
など)、
イベントバスは 先程作成したカスタムイベントバス とします。
イベントパターンは下記のようにします。 "AwsAccountId"
キー値であるリスト内に
「通知させたい AWSアカウントID」を入力していきます。
{ "detail": { "findings": { "AwsAccountId": ["1234567890XX", "1234567890YY", "1234567890ZZ"] } } }
ターゲットは 先程作成した SNSトピックとしましょう。
以上で リソース作成は完了です。
追加で別に通知させたいプロジェクト(AWSアカウント)がある場合は
「2. メッセージ送信するところまで」
節の手順を同じように実行します。
確認
作成した EventBridgeルール、およびメール通知を確認します。
① EventBridge Security Hub rule のメトリクス
TriggerdRules
と Invocations
が一致していて FailedInvocations
はありません。
正常にカスタムイベントバスへ送信できていること確認しました。
② EventBridge Accounts rule (AAA) のメトリクス
TriggerdRules
と Invocations
が一致していて FailedInvocations
はありません。
また 「① EventBridge Security Hub rule のメトリクス」と同じグラフとなっています。
正常に ① からイベントを受け取り、SNSトピックへ送信できていること確認しました。
③ メール通知
サブスクリプション先のアドレスへメール通知ができていること確認しました。
※今回はメッセージの整形までは行っていないです。行い場合は以下ブログを参照ください。
おわりに
以上、マルチアカウントサービスの(柔軟な)通知アーキテクチャ例を考えてみました。
この要件が出てきたときに、始めは Step Functions など活用したほうが良いかなと思っていました。 ある程度シンプルな振り分けであれば、EventBridgeのイベント連携のみで、なんとかなることを確かめられて良かったです。
補足: 今回作成に使った Terraform コード(サンプル)を下記に置いています。